package com.xiannimei.util;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.xiannimei.BusinessException;

public class StringUtil{
	public static final char[] ALPHEBIC = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

	public static final char[] ALPHEBIC_AND_NUMBER_UPPER = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
			// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
			// 'n', 'o', 'p', 'q', 'r', 's',
			// 't', 'u', 'v', 'w', 'x', 'y', 'z',
			'1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

	public static final char[] ALPHEBIC_AND_NUMBER_LOWER = new char[] {
			// 'A', 'B', 'C', 'D', 'E', 'F', 'G',
			// 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
			// 'U', 'V', 'W', 'X', 'Y', 'Z',
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

	public static final char[] ALPHEBIC_AND_NUMBER = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

	public static final char[] NUMBER = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

	public static final char[] ALPHEBIC_AND_NUMBER_UPPER_SEP = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

	public static final String DELIM = ",";

	public static final char[] RANDOMSET = new char[] { '1', '9', 'D', '8', 'A', '3', '0', '5', '4', 'E', '7', 'F', '6', 'B', '2', 'C' };
	public static final char[][] DIGITMATRIX = new char[][] { { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }, { 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' },
			{ 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l' }, { 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-', '_' } };

	public static final String BINARY_16ZEROS = "0000000000000000";
	
	public static String join(List<? extends String> list) {
		return join(list, DELIM);
	}

	public static String join(String[] arr) {
		return join(arr, DELIM);
	}

	public static String join(List<? extends String> list, String seperator) {
		if (list == null || list.size() == 0)
			return "";
		return join(list.toArray(new String[0]), DELIM);
	}

	public static String join(String[] arr, String seperator) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < arr.length; i++)
			sb.append(seperator + arr[i]);
		if (sb.length() > 0)
			sb.delete(0, seperator.length());
		return sb.toString();
	}

	public static String getAlphaOrder(int order) {
		StringBuffer sb = new StringBuffer();
		int size = ALPHEBIC.length;
		int i = order - 1;
		if (i < 0)
			throw new IllegalArgumentException();
		while (i >= size) {
			int j = i % size;
			i = i / size - 1;
			sb.insert(0, ALPHEBIC[j]);
		}
		sb.insert(0, ALPHEBIC[i]);
		return sb.toString();
	}

	public static String upcaseFirstLetter(String str) {
		if (str == null) {
			return null;
		}
		String firstChar = str.substring(0, 1);
		return firstChar.toUpperCase() + str.substring(1, str.length());
	}
	public final static boolean isContain(Object text,String beIncludedString){
		if (null == text){
			return false;
		}
		return text.toString().indexOf(beIncludedString) != -1;
	}
	public static String[] getFormatedIncreasedString(String firstString, int stepNum, int count) {
		if (firstString == null) {
			return null;
		}
		Pattern p = Pattern.compile("([0-9]+)$");
		Matcher m = p.matcher(firstString);

		if (m.find()) {

			int dIndex = m.start();
			String prefix = firstString.substring(0, dIndex);
			String suffix = firstString.substring(dIndex);
			/*
			 * int index = suffix.length(); if (suffix.endsWith("0")) { index =
			 * suffix.length() - 1; if (suffix.lastIndexOf("0", index) > 0) {
			 * prefix += suffix.substring(0, suffix.lastIndexOf("0", index));
			 * suffix = suffix.substring(suffix.lastIndexOf("0", index)); } }
			 * else { prefix += suffix.substring(0, suffix.lastIndexOf("0",
			 * index) + 1); suffix = suffix.substring(suffix.lastIndexOf("0",
			 * index) + 1); }
			 */

			int suffixLenth = suffix.length();

			long in = Long.parseLong(suffix);
			String[] value = new String[count];
			value[0] = firstString;
			for (int i = 1; i < count; i++) {
				long lastNum = in + stepNum * i;
				String last = Long.toString(lastNum);
				if (last.length() < suffixLenth) {
					last = formatLong(lastNum, suffixLenth);
				}
				value[i] = prefix + last;

			}
			return value;
		}
		return null;
	}

	public static String formatLong(long num, int length) {
		String number = Long.toString(num);
		while (number.length() < length) {
			number = "0" + number;
		}
		return number;
	}

	public static String formatDate(Date date, String pattern) {
		SimpleDateFormat dateTimeFormat = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
		dateTimeFormat.applyPattern(pattern);
		return dateTimeFormat.format(date);
	}

	public static String getRandomUpperStr(int strLength) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strLength; i++) {
			int j = (int) (Math.random() * ALPHEBIC_AND_NUMBER_UPPER.length);
			sb.append(ALPHEBIC_AND_NUMBER_UPPER[j]);
		}
		return sb.toString();
	}

	public static String getRandomUpperSepStr(int strLength) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strLength; i++) {
			int j = (int) (Math.random() * ALPHEBIC_AND_NUMBER_UPPER_SEP.length);
			sb.append(ALPHEBIC_AND_NUMBER_UPPER_SEP[j]);
		}
		return sb.toString();
	}

	public static String getRandomLowerStr(int strLength) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strLength; i++) {
			int j = (int) (Math.random() * ALPHEBIC_AND_NUMBER_LOWER.length);
			sb.append(ALPHEBIC_AND_NUMBER_LOWER[j]);
		}
		return sb.toString();
	}

	public static String getRandomStrAll(int strLength) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strLength; i++) {
			int j = (int) (Math.random() * ALPHEBIC_AND_NUMBER.length);
			sb.append(ALPHEBIC_AND_NUMBER[j]);
		}
		return sb.toString();
	}

	public static String getRandomStrNum(int strLength) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strLength; i++) {
			int j = (int) (Math.random() * NUMBER.length);
			sb.append(NUMBER[j]);
		}
		return sb.toString();
	}
	
	public static String decipheredString(String str) throws UnsupportedEncodingException {
        String returnStr = null;
        if (str != null && !str.equals("")) {
            returnStr = new String(decipheredHexByte(str), "ISO8859-1").trim();
        }
        return returnStr;
    }

    public static String cipheredString(String str) throws UnsupportedEncodingException {
        String returnStr = null;
        if (str != null && !str.equals("")) {
            returnStr = getCipheredHexStr(formatString(str,16).getBytes("ISO8859-1"));
        }
        return returnStr;
    }
    
    private static String getCipheredHexStr(byte[] bs) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bs.length; i++)
            sb.append(cipheredByteHex(bs[i]));
        String s = sb.toString();

        int ri3 = (int) (Math.random() * 16) + 1;
        String left = s.substring(0, ri3);
        String right = s.substring(ri3);
        s = "" + RANDOMSET[ri3 - 1] + right + left;
        return s;
    }

    private static String cipheredByteHex(byte ib) {
        int ri1 = (int) (Math.random() * 4);
        int ri2 = (int) (Math.random() * 4);
        char[] ob = new char[2];
        ob[0] = DIGITMATRIX[ri1][(ib >>> 4) & 0X0F];
        ob[1] = DIGITMATRIX[ri2][ib & 0X0F];
        String s = new String(ob);
        return s;
    }

    private static byte[] decipheredHexByte(String str) {
        char randomSeed = str.toCharArray()[0];
        int i = 0;
        for (i = 0; i < RANDOMSET.length; i++) {
            if (RANDOMSET[i] == randomSeed)
                break;
        }
        int length = str.length();
        String right = str.substring(1, length - i - 1);
        String left = str.substring(length - i - 1, length);
        String correctOrderStr = left + right;

        char[] originCharArray = correctOrderStr.toCharArray();
        for (int j = 0; j < originCharArray.length; j++) {
            char c = originCharArray[j];
            if ((c <= '0' && c >= '9') || (c <= 'A' && c >= 'F'))
                continue;
            boolean flag = false;
            for (int k = 0; k < 4; k++) {
                for (int m = 0; m < 16; m++) {
                    if (DIGITMATRIX[k][m] == c) {
                        originCharArray[j] = DIGITMATRIX[0][m];
                        flag = true;
                        break;
                    }
                }
                if (flag)
                    break;
            }
        }
        return longHexByte(new String(originCharArray));
    }

    private static byte[] longHexByte(String s) {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            b[i] = shortHexByte(s.substring(i * 2, i * 2 + 2));
        }
        return b;
    }

    private static byte shortHexByte(String s) {
        int val = Integer.parseInt(s, 16);
        return (byte) (val & 0XFF);
    }
   
    public static String formatString(String str, int length) {
        while (str.length() < length) {
            str = " " + str;
        }
        return str;
    }
    
    public static String converStr(String s){ 
    	if(s ==null)
    		return null;
    	else
    	return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
    }
    
    public static String toBinaryString(int i){
    	String bi = Integer.toBinaryString(i);
    	int length = bi.length();
    	if(length == 16) return bi;
    	if(length < 16){
    		return BINARY_16ZEROS.substring(length) + bi;
    	}else{
    		return BINARY_16ZEROS.substring(length) + bi;
    	}    		
    }
    
    public static String getEmailDomain(String mailAddr) {
        if (mailAddr == null || mailAddr.indexOf('@') == -1)
            throw new BusinessException("邮件格式错误");
        int delim = mailAddr.indexOf('@');
        return mailAddr.substring(delim + 1);
    }
    
	public static boolean isBlank(String str) {
		if (null == str) {
			return true;
		} else if("".equals(str)){
			return true;
		}else{
			return false;
		}
	}
	public static boolean isNotBlank(String str) {
		return !isBlank(str);
	}
	
	/**
	 * 中文字符串截取（来自于网络）
	 * @param str 源字符串
	 * @param length 截取长度（单位：字节）
	 * @param suffix 后缀
	 * @return
	 */
	public static String subStringByte(final String str, final int length, final String suffix) {
		if (str == null) {
			return str;
		}
		
		int suffixLen = isBlank(suffix) ? 0 : suffix.length();
		
		final StringBuffer sbuffer = new StringBuffer();
		final char[] chr = str.trim().toCharArray();
		int len = 0;
		for (int i = 0; i < chr.length; i++) {
			
			if (chr[i] >= 0xa1) {
				len += 2;
			} else {
				len++;
			}
		}
		
		if(len <= length){
			return str;
		}
		
		len = 0;
		for (int i = 0; i < chr.length; i++) {
 
			if (chr[i] >= 0xa1) {
				len += 2;
				if (len + suffixLen > length) {
					break;
				}else {
					sbuffer.append(chr[i]);
				}
			} else {
				len++;
				if (len + suffixLen > length) {
					break;
				}else {
					sbuffer.append(chr[i]);
				}
			}
		}
		sbuffer.append(suffix);
		
		return sbuffer.toString();
	}

	
	/**========================================
	 * 接收一个String类型的参数，并将其转化为中文金额的大写方式  
	 * 例如 123.45 --> 壹佰贰拾叁元肆角伍分  
	 * ========================================
	 */
	 public static String uppercaseCurrenty(java.math.BigDecimal val){
		try {
			return stringToUpperAmount(val.toString());
		} catch (NumberFormatException e) {
			System.out.println("非法数据，请检查！");
			return "非法数据，请检查";
		}
	 }
	 public static String uppercaseCurrenty(float val){
		return stringToUpperAmount(val + "");
	 }
	 
	private static String stringToUpperAmount(String s){
		try {
			float f = Float.valueOf(s);
			if (f < 0) {
				System.out.println("非法数据，请检查！");
				return "非法数据，请检查";
			} else {
				return cleanZero(splitNum(roundString(s)));
			}
		} catch (NumberFormatException e) {
			System.out.println("非法数据，请检查！");
			return "非法数据，请检查";
		}  
	}
	
    /**  
     * 把用户输入的数以小数点为界分割开来，并调用 numFormat() 方法  
     * 进行相应的中文金额大写形式的转换  
     * 注：传入的这个数应该是经过 roundString() 方法进行了四舍五入操作的  
     * @param s String  
     * @return 转换好的中文金额大写形式的字符串  
     */  
    private static String splitNum(String s) {   
        // 如果传入的是空串则继续返回空串   
        if("".equals(s)) {   
            return "";   
        }   
        // 以小数点为界分割这个字符串   
        int index = s.indexOf(".");   
        // 截取并转换这个数的整数部分   
        String intOnly = s.substring(0, index);   
        String part1 = numFormat(1, intOnly);   
        // 截取并转换这个数的小数部分   
        String smallOnly = s.substring(index + 1);   
        String part2 = numFormat(2, smallOnly);   
        // 把转换好了的整数部分和小数部分重新拼凑一个新的字符串   
        String newS = part1 + part2;
        return newS;
    }   
           
    /**  
     * 对传入的数进行四舍五入操作  
     * @param s String 从命令行输入的那个数  
     * @return 四舍五入后的新值  
     */  
    private static String roundString(String s) {   
        // 如果传入的是空串则继续返回空串   
        if("".equals(s)) {   
            return "";   
        }   
        // 将这个数转换成 double 类型，并对其进行四舍五入操作   
        double d = Double.parseDouble(s);   
        // 此操作作用在小数点后两位上     1.233  123.8/100   
        d = (d * 100 + 0.5) / 100;   
        // 将 d 进行格式化   
        s = new java.text.DecimalFormat("##0.000").format(d);   
        // 以小数点为界分割这个字符串   
        int index = s.indexOf(".");   
        // 这个数的整数部分   
        String intOnly = s.substring(0, index);   
        // 规定数值的最大长度只能到万亿单位，否则返回 "0"   
        if(intOnly.length() > 13) {   
            System.out.println("输入数据过大！（整数部分最多13位！）");   
            return "";   
        }   
        // 这个数的小数部分   
        String smallOnly = s.substring(index + 1);   
        // 如果小数部分大于两位，只截取小数点后两位   
        if(smallOnly.length() > 2) {   
            String roundSmall = smallOnly.substring(0, 2);   
            // 把整数部分和新截取的小数部分重新拼凑这个字符串   
            s = intOnly + "." + roundSmall;   
        }   
        return s;   
    }   
       
    /**  
     * 把传入的数转换为中文金额大写形式  
     * @param flag int 标志位，1 表示转换整数部分，0 表示转换小数部分  
     * @param s String 要转换的字符串  
     * @return 转换好的带单位的中文金额大写形式  
     */  
    private static String numFormat(int flag, String s) {   
        int sLength = s.length();   
        // 货币大写形式   
        String bigLetter[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};   
        // 货币单位   
        String unit[] = {"元", "拾", "佰", "仟", "万",    
                // 拾万位到仟万位   
                "拾", "佰", "仟",   
                // 亿位到万亿位   
                "亿", "拾", "佰", "仟", "万"};   
        String small[] = {"分", "角"};   
        // 用来存放转换后的新字符串   
        String newS = "";   
        // 逐位替换为中文大写形式   
        for(int i = 0; i < sLength; i ++) {   
            if(flag == 1) {   
                // 转换整数部分为中文大写形式（带单位）   
                newS = newS + bigLetter[s.charAt(i) - 48] + unit[sLength - i - 1];   
            } else if(flag == 2) {   
                // 转换小数部分（带单位）   
                newS = newS + bigLetter[s.charAt(i) - 48] + small[sLength - i - 1];   
            }   
        }   
        return newS;   
    }   
       
    /**  
     * 把已经转换好的中文金额大写形式加以改进，清理这个字  
     * 符串里面多余的零，让这个字符串变得更加可观  
     * 注：传入的这个数应该是经过 splitNum() 方法进行处理，这个字  
     * 符串应该已经是用中文金额大写形式表示的  
     * @param s String 已经转换好的字符串  
     * @return 改进后的字符串  
     */  
    private static String cleanZero(String s) {   
        // 如果传入的是空串则继续返回空串   
        if("".equals(s)) {   
            return "";   
        }   
        // 如果用户开始输入了很多 0 去掉字符串前面多余的'零'，使其看上去更符合习惯   
        while(s.charAt(0) == '零') {   
            // 将字符串中的 "零" 和它对应的单位去掉   
            s = s.substring(2);   
            // 如果用户当初输入的时候只输入了 0，则只返回一个 "零"   
            if(s.length() == 0) {   
                return "零";   
            }   
        }   
        // 字符串中存在多个'零'在一起的时候只读出一个'零'，并省略多余的单位   
        String regex1[] = {"零仟", "零佰", "零拾"};   
        String regex2[] = {"零亿", "零万", "零元"};   
        String regex3[] = {"亿", "万", "元"};   
        String regex4[] = {"零角", "零分"};   
        // 第一轮转换把 "零仟", 零佰","零拾"等字符串替换成一个"零"   
        for(int i = 0; i < 3; i ++) {   
            s = s.replaceAll(regex1[i], "零");   
        }   
        // 第二轮转换考虑 "零亿","零万","零元"等情况   
        // "亿","万","元"这些单位有些情况是不能省的，需要保留下来   
        for(int i = 0; i < 3; i ++) {   
            // 当第一轮转换过后有可能有很多个零叠在一起   
            // 要把很多个重复的零变成一个零   
            s = s.replaceAll("零零零", "零");   
            s = s.replaceAll("零零", "零");   
            s = s.replaceAll(regex2[i], regex3[i]);   
        }
        // 第三轮转换把"零角","零分"字符串省略   
        for(int i = 0; i < 2; i ++) {  
            s = s.replaceAll(regex4[i], "");   
        }
        // 当"万"到"亿"之间全部是"零"的时候，忽略"亿万"单位，只保留一个"亿"   
        s = s.replaceAll("亿万", "亿");   
        return s;   
    }
    
}
